#pragma once
#include <map>
#include <memory>
#include "XnccType.h"

namespace xncc {
namespace foundation {
    namespace ChannelType {
        enum value : uint8_t
        {
            TCP_CHANNEL          = 1,
            THREAD_CHANNEL       = 2,
            WAKEUP_CHANNEL       = 3,
            TIMER_CHANNEL        = 4,
            CLIENT_INIT_CHANNEL  = 5,
            ACCEPT_CHANNEL       = 6,
            DGRAM_CHANNEL        = 7,
            DGRAM_ACCEPT_CHANNEL = 8,
        };

        inline const char* toString(const ChannelType::value type)
        {
            switch (type) {
                case TCP_CHANNEL: return "TCP_CHANNEL";
                case THREAD_CHANNEL: return "THREAD_CHANNEL";
                case WAKEUP_CHANNEL: return "WAKEUP_CHANNEL";
                case TIMER_CHANNEL: return "TIMER_CHANNEL";
                case CLIENT_INIT_CHANNEL: return "CLIENT_INIT_CHANNEL";
                case ACCEPT_CHANNEL: return "ACCEPT_CHANNEL";
                case DGRAM_CHANNEL: return "DGRAM_CHANNEL";
                case DGRAM_ACCEPT_CHANNEL: return "DGRAM_ACCEPT_CHANNEL";
            }
            return "UNKNOWN";
        }
    }  // namespace ChannelType

    class EventLoop;
    // 由于继承了enable_shared_from_this 不能在没有构造完成的情况下使用this指针
    class Channel : public std::enable_shared_from_this<Channel>
    {
      public:
        explicit Channel(EventLoop* loop, int sockfd, types::connection_id_t connId = types::NOT_CONNECTION_ID);
        virtual ~Channel();
        Channel(const Channel&)            = delete;
        Channel& operator=(const Channel&) = delete;

        Channel(const Channel&&)            = delete;
        Channel& operator=(const Channel&&) = delete;

        virtual ChannelType::value Type() = 0;
        virtual void               init();
        void                       setIndex(int idx) { idx_ = idx; }
        int                        index() const { return idx_; }

        virtual void handleClose(const std::string& reason);
        virtual void handleRead();
        virtual void handleWrite();
        virtual void handleError(const std::string& reason);

        void setReadCallBack(types::EventCallback read_func) { readCallback_ = std::move(read_func); }
        void setWriteCallback(types::EventCallback write_func) { writeCallback_ = std::move(write_func); }
        void setCloseCallback(std::function<void(const std::string&)> close_func)
        {
            closeCallback_ = std::move(close_func);
        }
        void setErrorCallback(std::function<void(const std::string&)> error_func)
        {
            errorCallback_ = std::move(error_func);
        }

        void enableReading();
        void disableReading();
        void enableWriting();
        void disableWriting();
        void disableAll();
        bool isNoneEvent() const;
        void remove();
        bool isWriting() const;
        bool isReading() const;
        int  fd() const { return fd_; }
        int  events() const { return events_; }

        auto connId() const -> types::connection_id_t { return connId_; }

        auto loopId() const -> types::thread_id_t;

        auto loopType() const -> types::IO_MULTI_MODE::value;

        auto UserFuncs() const -> const std::map<types::message_id_t, types::UserFunc>&;

        void RunTask(types::Task func);

      private:
        void update();

        EventLoop*             loop_;
        int                    fd_ = -1;
        types::connection_id_t connId_;

        /// channel 的 epoll事件
        int events_ = {0};
        int idx_    = {-1};

        ///< callback 函数
        types::EventCallback                    readCallback_;
        types::EventCallback                    writeCallback_;
        std::function<void(const std::string&)> closeCallback_;
        std::function<void(const std::string&)> errorCallback_;
    };
}  // namespace foundation
}  // namespace xncc
